package cn.rengy.web.framework.shiro.config;

import java.util.List;

import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.authc.pam.AuthenticationStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.DefaultHashService;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.rengy.web.framework.shiro.OnlyOneAuthenticationStrategy;
@Configuration
//@AutoConfigureBefore(ShiroConfiguration.class)
public class ShiroWebConfiguration {
	
	@Bean
	protected AuthenticationStrategy authenticationStrategy() {
		// 默认的实现 无法捕捉到异常
        return new OnlyOneAuthenticationStrategy();
    }
	
	@Bean
	protected SecurityManager securityManager(List<Realm> realms,AuthenticationStrategy authenticationStrategy) {  
    	DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 
    	ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
    	authenticator.setAuthenticationStrategy(authenticationStrategy);
    	securityManager.setAuthenticator(authenticator);
    	securityManager.setRealms(realms);
        //不开启shiro缓存
        //dwsm.setCacheManager(new SpringCacheManagerWrapper(cacheManager));
    	//无状态subjectFactory设置
    	DefaultSessionStorageEvaluator evaluator = (DefaultSessionStorageEvaluator)((DefaultSubjectDAO) securityManager.getSubjectDAO()).getSessionStorageEvaluator();
    	evaluator.setSessionStorageEnabled(Boolean.FALSE);
    	StatelessWebSubjectFactory subjectFactory = new StatelessWebSubjectFactory();
        securityManager.setSubjectFactory(subjectFactory);
        
        return securityManager;
    }
	@Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
	@Bean
    protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
		DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
		//初始化过滤器链规则有顺序
		//authc:登录后才能访问，Anon：不指定过滤器
		//chainDefinition.addPathDefinition("/login", "anon");
        //,roles[admin]
		chainDefinition.addPathDefinition("/authenticated/**/", "jwtLogin");//jwt登录
		//chainDefinition.addPathDefinition("/authenticated/**/", "authen");//匹配1个或多个路径
        //filterChainDefinitionMap.put("/endpointCatering", "authen");//websocket
		//chainDefinition.addPathDefinition("/endpointCatering", "jwtLogin");
		return chainDefinition;
    }
	@Bean
	protected PasswordService passwordService() {
		DefaultPasswordService defaultPasswordService=new DefaultPasswordService();
		DefaultHashService hashService=new DefaultHashService();
		ByteSource privateSalt=ByteSource.Util.bytes("rengy");
		SecureRandomNumberGenerator secureRandomNumberGenerator=new SecureRandomNumberGenerator();
		secureRandomNumberGenerator.setDefaultNextBytesSize(64);
    	hashService.setHashAlgorithmName("SHA-512");//算法名称
    	hashService.setPrivateSalt(privateSalt); //私盐，默认无  ,如果存在私盐，必定生成公共盐来保护私盐的完整性
    	hashService.setGeneratePublicSalt(true);//在用户没有传入公盐的情况下是否生成公盐，默认false
    	hashService.setRandomNumberGenerator(secureRandomNumberGenerator);//用于生成公盐。默认就这个  
    	hashService.setHashIterations(2); //生成Hash值的迭代次数
    	defaultPasswordService.setHashService(hashService);
		return defaultPasswordService;
	}
}

